package com.bsj.power.pls.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.bsj.power.common.config.exception.ApiException;
import com.bsj.power.common.config.global.JsonResult;
import com.bsj.power.common.config.global.JsonResultEnum;
import com.bsj.power.common.constant.NumericalConstants;
import com.bsj.power.common.def.dto.group.GroupDTO;
import com.bsj.power.common.def.entity.group.Group;
import com.bsj.power.common.def.entity.personnel.Personnel;
import com.bsj.power.common.def.vo.pls.GroupTreeVO;
import com.bsj.power.common.def.vo.pls.GroupVO;
import com.bsj.power.common.mapper.GroupMapper;
import com.bsj.power.common.mapper.PersonnelMapper;
import com.bsj.power.common.util.ParamCheckUtil;
import com.bsj.power.pls.service.GroupService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author LiJiaXin
 * @version 1.0.0
 * @description GroupServiceImpl
 * @time 2024/4/25 19:23
 */
@Service
public class GroupServiceImpl implements GroupService {

    @Resource
    private GroupMapper groupMapper;

    @Resource
    private PersonnelMapper personnelMapper;

    /**
     * 添加组织
     *
     * @param groupDTO
     * @return com.bsj.power.common.config.global.JsonResult
     * @author ljx
     * @time 2024/4/25 19:43
     */
    @Override
    @Transactional
    public JsonResult addGroup(GroupDTO groupDTO) {
        paramCheck(groupDTO);
        Group group = new Group();
        BeanUtils.copyProperties(groupDTO, group);
        if (groupMapper.insert(group) > NumericalConstants.ZERO) {
            return JsonResult.success();
        } else {
            return JsonResult.fail();
        }
    }

    /**
     * 删除组织
     *
     * @param groupId
     * @return com.bsj.power.common.config.global.JsonResult
     * @author ljx
     * @time 2024/4/25 19:43
     */
    @Override
    @Transactional
    public JsonResult deleteGroup(Integer groupId) {
        ParamCheckUtil.isNull(groupId);
        ParamCheckUtil.isNull(groupMapper.selectById(groupId), JsonResultEnum.GROUP_NOT_EXIST);
        //如果该组织下有人员则无法删除
        if (personnelMapper.exists(new QueryWrapper<Personnel>().eq("group_id", groupId))) {
            throw new ApiException(JsonResultEnum.PERSONNEL_NOT_NULL);
        }
        //如果该组织下存有子组织则无法删除
        if (groupMapper.exists(Wrappers.<Group>lambdaQuery().eq(Group::getParentId, groupId))) {
            throw new ApiException(JsonResultEnum.GROUP_EXIST_SON);
        }
        if (groupMapper.deleteById(groupId) > NumericalConstants.ZERO) {
            return JsonResult.success();
        } else {
            return JsonResult.fail();
        }
    }

    /**
     * 修改组织
     *
     * @param groupDTO
     * @return com.bsj.power.common.config.global.JsonResult
     * @author ljx
     * @time 2024/4/25 19:43
     */
    @Override
    @Transactional
    public JsonResult updateGroup(GroupDTO groupDTO) {
        Group oldGroup = groupMapper.selectById(groupDTO.getGroupId());
        ParamCheckUtil.isNull(oldGroup, JsonResultEnum.GROUP_NOT_EXIST);
        if (!oldGroup.getParentId().equals(groupDTO.getParentId())) {
            throw new ApiException(JsonResultEnum.PARENT_GROUP_CANNOT_UPDATE);
        }
        paramCheck(groupDTO);
        Group group = new Group();
        BeanUtils.copyProperties(groupDTO, group);
        if (groupMapper.updateById(group) > NumericalConstants.ZERO) {
            return JsonResult.success();
        } else {
            return JsonResult.fail();
        }
    }

    /**
     * 获取单个组织
     *
     * @param groupId
     * @return com.bsj.power.common.def.vo.pls.GroupVO
     * @author ljx
     * @time 2024/4/25 19:43
     */
    @Override
    public GroupVO getGroupById(Integer groupId) {
        ParamCheckUtil.isNull(groupId);
        Group group = groupMapper.selectById(groupId);
        ParamCheckUtil.isNull(group, JsonResultEnum.GROUP_NOT_EXIST);
        GroupVO groupVO = new GroupVO();
        BeanUtils.copyProperties(group, groupVO);
        return groupVO;
    }

    /**
     * 获取组织树
     *
     * @return java.util.List<com.bsj.power.common.def.vo.pls.GroupTreeVO>
     * @author ljx
     * @time 2024/4/25 19:44
     */
    @Override
    public List<GroupTreeVO> getGroupTree() {
        List<GroupTreeVO> groupTreeVOS = new LinkedList<>();
        List<Group> groups = groupMapper.selectList(null);
        //类型转换
        Map<Integer, GroupTreeVO> groupTreeMap = groups.stream().map(group -> {
            GroupTreeVO groupTreeVO = new GroupTreeVO();
            BeanUtils.copyProperties(group, groupTreeVO);
            return groupTreeVO;
        }).collect(Collectors.toMap(GroupTreeVO::getGroupId, a -> a, (k1, k2) -> k1));

        groups.stream().forEach(group -> {
            //当前车组
            GroupTreeVO groupTreeVO = groupTreeMap.get(group.getGroupId());
            //当前车组的父车组
            GroupTreeVO parentGroupTreeVO = groupTreeMap.get(group.getParentId());
            //不为空说明有上级车组
            if (parentGroupTreeVO != null) {
                if (CollectionUtils.isEmpty(parentGroupTreeVO.getChildren())) {
                    List<GroupTreeVO> groupTreeVOList = new LinkedList<>();
                    groupTreeVOList.add(groupTreeVO);
                    parentGroupTreeVO.setChildren(groupTreeVOList);
                } else {
                    parentGroupTreeVO.getChildren().add(groupTreeVO);
                }
            } else {
                //最上层车组
                if (CollectionUtils.isEmpty(groupTreeVO.getChildren())) {
                    groupTreeVO.setChildren(new LinkedList<>());
                }
                groupTreeVOS.add(groupTreeVO);
            }
        });
        return groupTreeVOS;
    }

    /**
     * 获取指定组织的所有下级或上级组织id（包括本身）
     *
     * @param groupId
     * @param type    1:上级 2:下级
     * @return java.util.List<java.lang.Integer>
     * @author ljx
     * @time 2024/7/9 11:55
     */
    @Override
    public List<Integer> getGroupIds(Integer groupId, Integer type) {
        Set<Integer> set = new HashSet<>();
        //需要查询的下级id
        Set<Integer> groupIds = new HashSet<>() {
            {
                add(groupId);
                set.add(groupId);
            }
        };
        if (type == 1) {
            getSuUId(set, groupIds);
        } else {
            getLoUId(set, groupIds);
        }
        return set.stream().collect(Collectors.toList());
    }

    /**
     * 获取上级组织id
     *
     * @param set
     * @param groupIds
     * @return void
     * @author ljx
     * @time 2024/7/9 11:59
     */
    private void getSuUId(Set<Integer> set, Set<Integer> groupIds) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.in("group_id", groupIds);
        queryWrapper.select("parent_id");
        List<Group> groupList = groupMapper.selectList(queryWrapper);
        List<Integer> groupIdList = groupList.stream().map(Group::getParentId).collect(Collectors.toList());
        groupIdList.remove(new Integer(-1));
        if (!CollectionUtils.isEmpty(groupIdList)) {
            groupIds.clear();
            for (Integer groupId : groupIdList) {
                set.add(groupId);
                groupIds.add(groupId);
            }
            getSuUId(set, groupIds);
        }
    }

    /**
     * 获取下级组织id
     *
     * @param set
     * @param groupIds
     * @return void
     * @author ljx
     * @time 2024/7/9 12:04
     */
    private void getLoUId(Set<Integer> set, Set<Integer> groupIds) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.in("parent_id", groupIds);
        queryWrapper.select("group_id");
        List<Group> groupList = groupMapper.selectList(queryWrapper);
        if (!CollectionUtils.isEmpty(groupList)) {
            groupIds.clear();
            for (Group group : groupList) {
                Integer groupId = group.getGroupId();
                set.add(groupId);
                groupIds.add(groupId);
            }
            getLoUId(set, groupIds);
        }
    }

    /**
     * 参数校验
     *
     * @param groupDTO
     * @return void
     * @author ljx
     * @time 2024/4/25 19:57
     */
    private void paramCheck(GroupDTO groupDTO) {
        Integer parentId = groupDTO.getParentId();
        if (!parentId.equals(NumericalConstants.NEGATIVE_ONE)) {
            ParamCheckUtil.isNull(groupMapper.selectById(parentId), JsonResultEnum.PARENT_GROUP_NOT_EXIST);
        }
        //去重校验
        Integer groupId = groupDTO.getGroupId();
        QueryWrapper<Group> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("group_name", groupDTO.getGroupName());
        if (groupId != null) {
            queryWrapper.ne("group_id", groupId);
        }
        if (groupMapper.exists(queryWrapper)) {
            throw new ApiException(JsonResultEnum.GROUP_NAME_EXIST);
        }
    }
}
